package com.hw.one.collect.zzcity.channel;

import com.alibaba.fastjson.JSON;
import com.hw.one.collect.data.IDataService;
import com.hw.one.collect.resource.BaseContext;
import com.hw.one.collect.zzcity.constants.ZzCityConstants;
import com.hw.one.collect.zzcity.memento.ZzCityCareTaker;
import com.hw.one.collect.zzcity.memento.ZzCityMemento;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpResponse;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 郑州市HttpClient入站绑定处理器
 * Created by Administrator on 2016/7/5.
 */
public class ZzCityHttpClientInboundHandler extends ChannelInboundHandlerAdapter {

    private static Logger log = Logger.getLogger(ZzCityHttpClientInboundHandler.class);

    private String dataService;
    private int key;

    public ZzCityHttpClientInboundHandler(String dataService,int key) {
        this.dataService = dataService;
        this.key = key;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof HttpResponse) {
            HttpResponse response = (HttpResponse) msg;
            log.debug("CONTENT_TYPE:" + response.headers().get(HttpHeaderNames.CONTENT_TYPE));
            log.debug("CONTENT_LENGTH:" + response.headers().get(HttpHeaderNames.CONTENT_LENGTH));
        }

        if (msg instanceof HttpContent) {
            HttpContent httpContent = (HttpContent) msg;
            ByteBuf byteBuf = httpContent.content();
            String result = byteBuf.toString(Charset.forName("UTF-8"));
            byteBuf.release();
            //处理数据
            Object data = processData(result);
            if(data != null){
                //数据完整性处理
                processDataIntegrity(data);
                IDataService dataService = (IDataService) BaseContext.getService(this.dataService);
                log.debug("处理序列："+this.key+"，数据服务：" + dataService.getClass().getName());
                try {
                    log.debug("处理序列："+this.key+"，执行插入开始");
                    dataService.insert(data);
                    log.debug("处理序列："+this.key+"，执行插入结束");
                    //删除备忘录
                    removeMemento();
                } catch (Exception e) {
                    //更新备忘录
                    updateMemento();
                    log.debug("处理序列："+this.key+"，执行插入异常");
                    log.error(e);
                    throw e;
                }
            }
            ctx.close();
        }

    }

    /**
     * 处理数据完整性，不完全的站点放到备忘录，继续拉取
     * @param data
     */
        private void processDataIntegrity(Object data) {
        String mementoUcode = ZzCityCareTaker.newInstance().get(key).getuCode();
        String comparedUcode = mementoUcode;//待对比的ucode
        if(StringUtils.isBlank(mementoUcode)){
            comparedUcode = ZzCityConstants.UCODE;
        }
        //所有站点集合
        List<String> uCodeList = Arrays.asList(comparedUcode.split(","));
        List<String> uCodes = new ArrayList<>(uCodeList);
        //遍历数据去掉已拉取到站点
        List<Map> dataList = (List<Map>) data;
        for (Map map : dataList) {
            String uCode = (String) map.get("UCode");
            if(uCodes.contains(uCode)){
                uCodes.remove(uCode);
            }
        }
        if(uCodes.size() != 0){
            String[] uCodeArr = uCodes.toArray(new String[uCodes.size()]);
            String uCode =StringUtils.join(uCodeArr,",");
            //更新备忘录，创建遗漏数据
            updateOmitMemento(uCode);
        }else{
            //更新备忘录为未改变状态，使其可以移除
            updateIntegrityMemento();
        }

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("处理序列："+this.key+"，郑州市客户端处理器", cause);
        cause.printStackTrace();
        ctx.close();
    }

    /**
     * 处理请求数据
     *
     * @param data
     * @return
     */
    private Object processData(String data) {
        String processedData = StringUtils.substring(data,1,data.length()-1);
        String jsonStr = processedData.replace("\\","");
        log.debug("处理序列："+this.key+",处理后请求结果：" + jsonStr);
        try {
            List<Map> dataList = JSON.parseArray(jsonStr, Map.class);
            if (dataList.size() == 0) {
                //更新备忘录
                updateMemento();
                return null;
            }
            return dataList;
        } catch (Exception e) {
            log.error("请求数据解析异常",e);
            try {
                Map<String, String> errMap = JSON.parseObject(jsonStr, Map.class);
                String statusCode = errMap.get("StatusCode");
                String message = errMap.get("Message");
                log.error("请求异常：{错误码：" + statusCode + "|错误消息：" + message+"}");
            } catch (Exception e1) {
                log.error("请求数据异常：",e1);
            }
            //更新备忘录
            updateMemento();
            return null;
        }
    }

    /**
     * 成功，移除备忘录
     */
    private void removeMemento(){
        ZzCityMemento memento = ZzCityCareTaker.newInstance().get(key);
        if(!memento.isChange()){
            ZzCityCareTaker.newInstance().remove(key);
        }
        log.info("郑州市移除备忘录");
    }

    /**
     * 更新备忘录
     */
    private void updateMemento() {
        log.info("郑州市更新备忘录");
        //记录错误请求
        ZzCityMemento memento = ZzCityCareTaker.newInstance().get(key);
        //存在就更新，否则就是之前未添加成功
        if(memento != null){
            ZzCityCareTaker.newInstance().update(key,memento);
        }
    }

    /**
     * 创建遗漏站点数据拉取备忘录
     * @param uCode
     */
    private void updateOmitMemento(String uCode){
        log.info("创建遗漏站点数据拉取备忘录");
        //记录错误请求
        ZzCityMemento memento = ZzCityCareTaker.newInstance().get(key);
        //存在就更新，否则就是之前未添加成功
        if(memento != null){
            memento.setCount(0);
            memento.setChange(true);
            memento.setuCode(uCode);
            ZzCityCareTaker.newInstance().update(key,memento);
        }
    }

    /**
     * 更新备忘录为未改变状态，使其可以移除
     */
    private void updateIntegrityMemento(){
        log.info("更新备忘录为未改变状态，使其可以移除");
        //记录错误请求
        ZzCityMemento memento = ZzCityCareTaker.newInstance().get(key);
        //存在就更新，否则就是之前未添加成功
        if(memento != null){
            memento.setChange(false);
            ZzCityCareTaker.newInstance().update(key,memento);
        }
    }

}
